home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.67 / src / clock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-20  |  5.7 KB  |  252 lines

  1. /*
  2.  * Copyright (c) 1983 Eric P. Allman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *    This product includes software developed by the University of
  17.  *    California, Berkeley and its contributors.
  18.  * 4. Neither the name of the University nor the names of its contributors
  19.  *    may be used to endorse or promote products derived from this software
  20.  *    without specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34.  
  35. #ifndef lint
  36. static char sccsid[] = "@(#)clock.c    5.10 (Berkeley) 3/4/91";
  37. #endif /* not lint */
  38.  
  39. # include "sendmail.h"
  40. # include <signal.h>
  41.  
  42. /*
  43. **  SETEVENT -- set an event to happen at a specific time.
  44. **
  45. **    Events are stored in a sorted list for fast processing.
  46. **    An event only applies to the process that set it.
  47. **
  48. **    Parameters:
  49. **        intvl -- intvl until next event occurs.
  50. **        func -- function to call on event.
  51. **        arg -- argument to func on event.
  52. **
  53. **    Returns:
  54. **        none.
  55. **
  56. **    Side Effects:
  57. **        none.
  58. */
  59.  
  60. static void tick();
  61.  
  62. EVENT *
  63. setevent(intvl, func, arg)
  64.     time_t intvl;
  65.     int (*func)();
  66.     int arg;
  67. {
  68.     register EVENT **evp;
  69.     register EVENT *ev;
  70.     auto time_t now;
  71.  
  72.     if (intvl <= 0)
  73.     {
  74.         syserr("setevent: intvl=%ld\n", intvl);
  75.         return (NULL);
  76.     }
  77.  
  78.     (void) time(&now);
  79.  
  80.     /* search event queue for correct position */
  81.     for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link)
  82.     {
  83.         if (ev->ev_time >= now + intvl)
  84.             break;
  85.     }
  86.  
  87.     /* insert new event */
  88.     ev = (EVENT *) xalloc(sizeof *ev);
  89.     ev->ev_time = now + intvl;
  90.     ev->ev_func = func;
  91.     ev->ev_arg = arg;
  92.     ev->ev_pid = getpid();
  93.     ev->ev_link = *evp;
  94.     *evp = ev;
  95.  
  96.     if (tTd(5, 5))
  97.         printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n",
  98.             intvl, now + intvl, func, arg, ev);
  99.  
  100.     tick();
  101.     return (ev);
  102. }
  103. /*
  104. **  CLREVENT -- remove an event from the event queue.
  105. **
  106. **    Parameters:
  107. **        ev -- pointer to event to remove.
  108. **
  109. **    Returns:
  110. **        none.
  111. **
  112. **    Side Effects:
  113. **        arranges for event ev to not happen.
  114. */
  115.  
  116. clrevent(ev)
  117.     register EVENT *ev;
  118. {
  119.     register EVENT **evp;
  120.  
  121.     if (tTd(5, 5))
  122.         printf("clrevent: ev=%x\n", ev);
  123.     if (ev == NULL)
  124.         return;
  125.  
  126.     /* find the parent event */
  127.     (void) signal(SIGALRM, SIG_IGN);
  128.     for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
  129.     {
  130.         if (*evp == ev)
  131.             break;
  132.     }
  133.  
  134.     /* now remove it */
  135.     if (*evp != NULL)
  136.     {
  137.         *evp = ev->ev_link;
  138.         free((char *) ev);
  139.     }
  140.  
  141.     /* restore clocks and pick up anything spare */
  142.     tick();
  143. }
  144. /*
  145. **  TICK -- take a clock tick
  146. **
  147. **    Called by the alarm clock.  This routine runs events as needed.
  148. **
  149. **    Parameters:
  150. **        none.
  151. **
  152. **    Returns:
  153. **        none.
  154. **
  155. **    Side Effects:
  156. **        calls the next function in EventQueue.
  157. */
  158.  
  159. static void
  160. tick()
  161. {
  162.     register time_t now;
  163.     register EVENT *ev;
  164.     int mypid = getpid();
  165.  
  166.     (void) signal(SIGALRM, SIG_IGN);
  167.     (void) alarm(0);
  168.     now = curtime();
  169.  
  170.     if (tTd(5, 4))
  171.         printf("tick: now=%ld\n", now);
  172.  
  173.     while ((ev = EventQueue) != NULL &&
  174.            (ev->ev_time <= now || ev->ev_pid != mypid))
  175.     {
  176.         int (*f)();
  177.         int arg;
  178.         int pid;
  179.  
  180.         /* process the event on the top of the queue */
  181.         ev = EventQueue;
  182.         EventQueue = EventQueue->ev_link;
  183.         if (tTd(5, 6))
  184.             printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev,
  185.                 ev->ev_func, ev->ev_arg, ev->ev_pid);
  186.  
  187.         /* we must be careful in here because ev_func may not return */
  188.         (void) signal(SIGALRM, tick);
  189. #ifdef SIGVTALRM
  190.         /* reset 4.2bsd signal mask to allow future alarms */
  191.         (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
  192. #endif SIGVTALRM
  193.  
  194.         f = ev->ev_func;
  195.         arg = ev->ev_arg;
  196.         pid = ev->ev_pid;
  197.         free((char *) ev);
  198.         if (pid != getpid())
  199.             continue;
  200.         if (EventQueue != NULL)
  201.         {
  202.             if (EventQueue->ev_time > now)
  203.                 (void) alarm((unsigned) (EventQueue->ev_time - now));
  204.             else
  205.                 (void) alarm(3);
  206.         }
  207.         (*f)(arg);
  208.         (void) alarm(0);
  209.         now = curtime();
  210.     }
  211.     (void) signal(SIGALRM, tick);
  212.     if (EventQueue != NULL)
  213.         (void) alarm((unsigned) (EventQueue->ev_time - now));
  214. }
  215. /*
  216. **  SLEEP -- a version of sleep that works with this stuff
  217. **
  218. **    Because sleep uses the alarm facility, I must reimplement
  219. **    it here.
  220. **
  221. **    Parameters:
  222. **        intvl -- time to sleep.
  223. **
  224. **    Returns:
  225. **        none.
  226. **
  227. **    Side Effects:
  228. **        waits for intvl time.  However, other events can
  229. **        be run during that interval.
  230. */
  231.  
  232. static bool    SleepDone;
  233.  
  234. sleep(intvl)
  235.     unsigned int intvl;
  236. {
  237.     static int endsleep();
  238.  
  239.     if (intvl == 0)
  240.         return;
  241.     SleepDone = FALSE;
  242.     (void) setevent((time_t) intvl, endsleep, 0);
  243.     while (!SleepDone)
  244.         pause();
  245. }
  246.  
  247. static
  248. endsleep()
  249. {
  250.     SleepDone = TRUE;
  251. }
  252.